%{
	open Ast

let parse_error s = 
	print_endline ("Erreur de grammaire : [ligne: "^(string_of_int !Lexer.ligne)^" | charactere: "^(string_of_int !Lexer.col)^"] : \""^(!Lexer.mot)^"\"");
;;

%}


%left MOINS	
%left MUL
%left DIV 
%left PLUS
%left NOT
%left ET
%left OU	
%left RT
%left BG

/* Déclaration des lexèmes */

%token <int> N
%token <float> D
%token <string> X
%token  INF SUP INFEGAL SUPEGAL EGAL DIFF
%token AFFECTATION 
%token TRUE FALSE
%token PARENTHESEOUVRANTE PARENTHESEFERMANTE
%token CROCHETOUVRANT CROCHETFERMANT						
%token INT
%token <string> MOTFONCTION MOTPROCEDURE
%token IF THEN ELSE WHILE DO END
%token IS VIRGULE POINTVIRGULE DEUXPOINTS  EOF
%token PLUS MOINS DIV NOT ET OU RT BG MUL
/* Point d'entrée */

%start programme
/*%type <programmedeclarationListe> listeprogrammedeclaration*/
%type <Ast.nProgrammePrincipal> programme

%%


programme :
| listeprogrammedeclaration statement EOF {Programme ($1,$2)}
;

listeprogrammedeclaration :
	{ [] }
| 	programmedeclarations {$1}
;

programmedeclarations :
	programmedeclaration { [$1] }
| 	programmedeclarations programmedeclaration { $1@[$2] }
;

programmedeclaration :
	MOTFONCTION nomfonction PARENTHESEOUVRANTE listeargumentsdeclaration PARENTHESEFERMANTE DEUXPOINTS typeT IS statement { NProgrammeFonction (NFonction ($2,$4,$7,$9)) }
| 	MOTPROCEDURE nomfonction PARENTHESEOUVRANTE listeargumentsdeclaration PARENTHESEFERMANTE IS statement { NProgrammeProcedure (NProcedure ($2,$4,$7)) }
;

unop :
	MOINS { 0 }
;

binop :
	PLUS {  Plus }
| 	MOINS { Moins }
| 	MUL {   Mult }
| 	DIV {   Div }
;

comparateur :
	INF { Inf }
| 	SUP { Sup }
| 	INFEGAL { InfEgal }
| 	SUPEGAL { SupEgal }
| 	EGAL { Egal }
| 	DIFF { Diff }
;

arithmetique :
	arithmetique_simple {$1}
| 	unop arithmetique_simple {NUnop ($2)}
| 	arithmetique_simple binop arithmetique {NBinOp ($1,$2,$3)}
;

arithmetique_simple:
	N { NN ($1) }
| 	variable { $1 }
| 	PARENTHESEOUVRANTE arithmetique PARENTHESEFERMANTE { $2 }
;

booleene :
	TRUE { NTrue }
| 	FALSE { NFalse }
| 	arithmetique comparateur arithmetique { NCmp ($1,$2,$3) }
| 	NOT booleene { NotBoolean ($2) }
| 	booleene ET booleene { NAnd ($1,$3) }
| 	booleene OU booleene { NOr ($1,$3) }
| 	PARENTHESEOUVRANTE booleene PARENTHESEFERMANTE { $2 }
;

variable :
	X { 
			NVariable($1,{entry=(-1)})
	};

nomfonction :
	X { $1 }
;

typeT :
	INT { "integer" };

appelfonction:
	nomfonction PARENTHESEOUVRANTE listearithmetique PARENTHESEFERMANTE { NAppel ($1,$3) }
;

instruction : 
	RT POINTVIRGULE { NReturn }
| 	RT arithmetique POINTVIRGULE { NReturnValeur ($2)}
| 	variable AFFECTATION arithmetique POINTVIRGULE { NAffectation ($1,$3)}
| 	appelfonction POINTVIRGULE { NAppelMethode ($1) }
| 	variable AFFECTATION appelfonction POINTVIRGULE { NAppelFonction ($1,$3) }
;

statement :
	instruction {NStatementInstruction $1}
| 	IF booleene THEN statement ELSE statement { NIf ($2,$4,$6) }
| 	WHILE booleene DO statement { NWhile ($2,$4) }
| 	BG listedeclarations listestatements END  { NBlock ($2,$3) }
;

listeargumentsdeclaration :
	{ Al ([]) }
| 	listeargumentsdeclarationvirgule { Al $1 }
;

listeargumentsdeclarationvirgule :
	argumentdeclaration { [$1] }
| 	listeargumentsdeclarationvirgule VIRGULE argumentdeclaration { $1@[$3] };

argumentdeclaration :
	variable DEUXPOINTS typeT { NArgument ($1,$3) }
;

listearithmetique :
	{ ArL [] }
| 	listeArithmetiqueVirgule { ArL $1 }
;

listeArithmetiqueVirgule :
	arithmetique { [$1] }
|	listeArithmetiqueVirgule VIRGULE arithmetique { $1@[$3] }
;

listevariables:
	listevariablesVirgule {  ListeVariable $1  }
;

listevariablesVirgule:
	variable { [$1] }
| 	listevariablesVirgule VIRGULE variable { $1@[$3] }
;

declaration :
	typeT listevariables POINTVIRGULE { NDeclaration ($1,$2) }
;

listedeclarations :
	{ DecList []  }
| 	declarations { DecList $1 }
;

declarations :
	declaration {  [$1] }
| 	declarations declaration { $1@[$2] }

listestatements :
	{ [] }
| 	statements { $1 }
;

statements:
	statement { [$1] }
| 	statements statement { $1@[$2] }
;

%%